package com.easyapi.server.utils;

import com.alibaba.druid.DbType;
import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.expr.*;
import com.alibaba.druid.sql.ast.statement.SQLSelect;
import com.alibaba.druid.sql.ast.statement.SQLSelectItem;
import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlCharExpr;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock;
import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlOutputVisitor;
import com.easyapi.common.param.api.InputParam;
import com.easyapi.common.param.api.OutputParam;
import com.easyapi.dao.entity.api.ApiCenterInterfaceInfo;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;

import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 向导模式--sql 生成
 */
public class GenerateSqlUtil {
    /**
     * select 语句生成---》后续编写通用mapper.xml
     *
     * @param interfaceInfo
     * @param paramMap
     * @return
     */
    public static String selectSql(ApiCenterInterfaceInfo interfaceInfo, Map<String, String> paramMap) {
        String inputParamsJson = interfaceInfo.getInputParams();
        String outputParamsJson = interfaceInfo.getOutputParams();
        Type inputType = new TypeToken<List<InputParam>>() {
        }.getType();
        Type outputType = new TypeToken<List<OutputParam>>() {
        }.getType();
        Gson gson = new Gson();
        List<InputParam> inputParams = gson.fromJson(inputParamsJson, inputType);
        List<OutputParam> outputParams = gson.fromJson(outputParamsJson, outputType);
        String tableName = interfaceInfo.getTableName();
        List<InputParam> params = null;
        String databasesName = interfaceInfo.getDatabasesName();
        //输入参数过滤，没有默认为true
        if (MapUtils.isNotEmpty(paramMap)) {
            params = inputParams.stream()
                    .filter(m -> paramMap.containsKey(m.getParamName()))
                    .collect(Collectors.toList());
        }
        SQLSelect sqlSelect = new SQLSelect();
        MySqlSelectQueryBlock queryBlock = new MySqlSelectQueryBlock();
        //构建输出参数
        for (OutputParam outputParam : outputParams) {
            SQLSelectItem sqlSelectItem = new SQLSelectItem(new SQLIdentifierExpr(outputParam.getBindField()));
            queryBlock.addSelectItem(sqlSelectItem);
        }
        //from 语句
        queryBlock.setFrom(new SQLIdentifierExpr(databasesName+"."+tableName));
        //输出语句构建
        if (CollectionUtils.isNotEmpty(params)){
            SQLExpr whereCondition = buildSelectCondition(params, paramMap);
            queryBlock.setFrom(whereCondition);
        }
        // 设置分页信息 todo 分页
        sqlSelect.setQuery(queryBlock);
        return sqlSelect.toString();
    }

    public static SQLExpr buildSelectCondition(List<InputParam> params, Map<String, String> paramMap) {
        SQLExpr whereCondition = null;

        for (InputParam param : params) {
            String operator = param.getOperator();
            String value = paramMap.get(param.getParamName());
            SQLExpr condition = null;

            // LIKE 操作符
            if (operator.equalsIgnoreCase("like")) {
                condition = new SQLBinaryOpExpr(
                        new SQLIdentifierExpr(param.getBindField()),
                        SQLBinaryOperator.Like,
                        new MySqlCharExpr("%" + value + "%"),
                        DbType.mysql
                );
            }

            // = 操作符
            else if (operator.equalsIgnoreCase("=")) {
                condition = new SQLBinaryOpExpr(
                        new SQLIdentifierExpr(param.getBindField()),
                        SQLBinaryOperator.Equality,
                        new MySqlCharExpr(value),
                        DbType.mysql
                );
            }

            // > 操作符
            else if (operator.equalsIgnoreCase(">")) {
                condition = new SQLBinaryOpExpr(
                        new SQLIdentifierExpr(param.getBindField()),
                        SQLBinaryOperator.GreaterThan,
                        new SQLIntegerExpr(Integer.parseInt(value)),
                        DbType.mysql
                );
            }

            // >= 操作符
            else if (operator.equalsIgnoreCase(">=")) {
                condition = new SQLBinaryOpExpr(
                        new SQLIdentifierExpr(param.getBindField()),
                        SQLBinaryOperator.GreaterThanOrEqual,
                        new SQLIntegerExpr(Integer.parseInt(value)),
                        DbType.mysql
                );
            }

            // < 操作符
            else if (operator.equalsIgnoreCase("<")) {
                condition = new SQLBinaryOpExpr(
                        new SQLIdentifierExpr(param.getBindField()),
                        SQLBinaryOperator.LessThan,
                        new SQLIntegerExpr(Integer.parseInt(value)),
                        DbType.mysql
                );
            }

            // <= 操作符
            else if (operator.equalsIgnoreCase("<=")) {
                condition = new SQLBinaryOpExpr(
                        new SQLIdentifierExpr(param.getBindField()),
                        SQLBinaryOperator.LessThanOrEqual,
                        new SQLIntegerExpr(Integer.parseInt(value)),
                        DbType.mysql
                );
            }

            // != 操作符
            else if (operator.equalsIgnoreCase("!=") || operator.equalsIgnoreCase("<>")) {
                condition = new SQLBinaryOpExpr(
                        new SQLIdentifierExpr(param.getBindField()),
                        SQLBinaryOperator.NotEqual,
                        new MySqlCharExpr(value),
                        DbType.mysql
                );
            }
            else if (operator.equalsIgnoreCase("in")) {
                SQLInListExpr inListExpr = new SQLInListExpr();
                inListExpr.setExpr(new SQLIdentifierExpr(param.getBindField()));

                // 将逗号分隔的字符串转换为 IN 列表
                String[] values = value.split(",");
                for (String val : values) {
                    inListExpr.addTarget(new MySqlCharExpr(val.trim()));
                }
                condition = inListExpr;
            }

            // 连接 WHERE 条件
            if (condition != null) {
                if (whereCondition == null) {
                    whereCondition = condition;
                } else {
                    whereCondition = new SQLBinaryOpExpr(
                            whereCondition,
                            SQLBinaryOperator.BooleanAnd,
                            condition,
                            DbType.mysql
                    );
                }
            }
        }
        return whereCondition;
    }
}
